package com.acc.sys.service;

import apijson.JSONResponse;
import apijson.RequestMethod;
import cn.dev33.satoken.stp.SaLoginConfig;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SmUtil;
import com.acc.sys.constants.TableNameConstants;
import com.acc.sys.enums.Judge;
import com.acc.sys.framework.AccParser;
import com.acc.utils.DbUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import static apijson.JSONObject.KEY_ID;
import static com.acc.sys.constants.TableNameConstants.*;

@Service
@AllArgsConstructor
public class AdminAuthService {
    /**
     * 登录
     *
     * @param username 用户名
     * @param password 密码
     * @return 登录信息
     */
    public JSONObject login(String username, String password) {
        JSONObject user = DbUtil.table(TableNameConstants.SYS_ADMIN)
                .where("username", username)
                .where("_password", SmUtil.sm3(password))
                .find();
        if (user == null) {
            throw new RuntimeException("账号/密码不正常");
        }
        StpUtil.login(user.getString("id"), SaLoginConfig.setExtra("roles", user.get("roles")).setExtra("super_admin", user.get("super_admin")));
        JSONArray permissions = new JSONArray();
        permissions.add("*:*:*");
        user.put("permissions", permissions);
        user.put("accessToken", StpUtil.getTokenValue());
        user.put("refreshToken", StpUtil.getTokenValue());
        DateTime dateTime = DateUtil.offsetSecond(DateUtil.date(), (int) StpUtil.getTokenTimeout());
        user.put("expires", DateUtil.format(dateTime, "yyyy/MM/dd HH:mm:ss"));
        JSONObject ret = new JSONObject();
        ret.put("data", user);
        return ret;
    }

    /**
     * @return 获取路由
     */
    public JSONArray routes() {
        //获取菜单
        JSONArray menuList = menuList();
        JSONArray array = new JSONArray();
        menuList.forEach(item -> array.add(createRoutes((JSONObject) item)));
        JSONObject menuMap = new JSONObject();
        array.forEach(item -> {
            JSONObject menuItem = (JSONObject) item;
            menuMap.put(menuItem.getString("id"), menuItem);
        });
        //拼接菜单
        JSONArray menuArray = new JSONArray();
        array.forEach(item -> {
            JSONObject menuItem = (JSONObject) item;
            if (StrUtil.equals(menuItem.getString("parent_id"), "0")) {
                menuArray.add(menuItem);
            } else {
                JSONObject parentMenu = menuMap.getJSONObject(menuItem.getString("parent_id"));
                if (parentMenu != null) {
                    if (parentMenu.getJSONArray("children") == null) {
                        parentMenu.put("children", new JSONArray());
                    }
                    parentMenu.getJSONArray("children").add(menuItem);

                }
            }
        });
        return menuArray;
    }

    private JSONObject createRoutes(JSONObject menu) {
        JSONObject route = new JSONObject();
        route.put("id", menu.get("id"));// id
        route.put("parent_id", menu.get("parent_id"));// id
        route.put("path", menu.get("path"));// 路由地址
        route.put("name", menu.get("name"));// 路由名称
        route.put("redirect", menu.get("redirect"));// 路由重定向
        route.put("component", menu.get("component"));

        JSONObject meta = new JSONObject();
        meta.put("title", menu.get("title"));
        meta.put("icon", menu.get("icon"));
        meta.put("rank", menu.get("rank"));
        meta.put("showLink", Judge.getYes(menu.getIntValue("show_link")));
        meta.put("extraIcon", menu.get("extra_icon"));
        meta.put("showParent", Judge.getYes(menu.getIntValue("show_parent")));
        meta.put("roles", menu.get("roles"));
        meta.put("auths", menu.get("auths"));
        meta.put("keepAlive", Judge.getYes(menu.getIntValue("keep_alive")));
        meta.put("frameSrc", menu.get("frame_src"));
        meta.put("frameLoading", Judge.getYes(menu.getIntValue("frame_loading")));
        meta.put("transition", menu.get("transition"));
        meta.put("hiddenTag", menu.get("hidden_tag"));
        meta.put("dynamicLevel", menu.get("dynamic_level"));
        meta.put("activePath", menu.get("active_path"));
        route.put("meta", meta);
        return route;
    }

    /**
     * @return 获取菜单列表
     */
    public JSONArray menuList() {
        if (StrUtil.equals("1", StpUtil.getExtra("super_admin").toString())) {
            return DbUtil.table(SYS_MENU).select(true);
        }
        //获取角色权限
        JSONArray merge = DbUtil.table(TableNameConstants.SYS_ROLE)
                .where("status", Judge.Is.getCode())
                .where("id{}", StpUtil.getExtra("roles"))
                .select(true);
        JSONArray permissionsList = new JSONArray();
        merge.forEach(obj -> {
            JSONObject item = (JSONObject) obj;
            permissionsList.addAll(item.getJSONArray("permissions"));
        });
        //获取菜单
        return DbUtil.table(SYS_MENU).where("id{}", permissionsList).select(true);
    }


    /**
     * 删除菜单及子菜单
     *
     * @param id 菜单ID
     * @return 删除菜单
     */
    public JSONObject deleteMenu(String id) {
        return deleteSub(SYS_MENU, id);
    }

    /**
     * 删除菜单及子菜单
     *
     * @param id 菜单ID
     * @return 删除菜单
     */
    public JSONObject deleteDept(String id) {
        return deleteSub(SYS_DEPT, id);
    }

    /**
     * 循环删除
     *
     * @param table 表名
     * @param id    id
     * @return 循环删除
     */
    private JSONObject deleteSub(String table, String id) {
        return deleteSub(table, id, "parent_id");
    }

    /**
     * 循环删除
     *
     * @param table         表名
     * @param id            id
     * @param parentIdFiled 父级字段名
     * @return 循环删除
     */
    private JSONObject deleteSub(String table, String id, String parentIdFiled) {
        JSONObject delete = DbUtil.table(table).delete(id);
        JSONArray select = DbUtil.table(table).where(parentIdFiled, id).select(true);
        select.forEach(o -> {
            JSONObject item = (JSONObject) o;
            deleteDept(item.getString("id"));
        });
        return delete;
    }

    /**
     * 保存管理员
     *
     * @param params 保存管理员
     * @return 保存管理员
     */
    public JSONObject saveAdmin(JSONObject params) {
        RequestMethod method = RequestMethod.POST;
        if (params.containsKey(KEY_ID) && params.getString(KEY_ID) != null) {
            method = RequestMethod.PUT;
        }
        if (params.containsKey("password")) {
            if(StrUtil.isNotEmpty(params.getString("password"))){
                params.put("_password", SmUtil.sm3(params.getString("password")));
            }
            params.remove("password");
        }
        JSONObject save = DbUtil.table(SYS_ADMIN).save(params, method);
        if (JSONResponse.isSuccess(save)) {
            return AccParser.extendSuccessResult(null);
        }
        return AccParser.extendErrorResult(null, new RuntimeException("新增用户失败"));
    }


}
